using System;
using Neural;

namespace XorNet
{
	/// <summary>
	/// Example of a network that learns the XOR problem
	/// </summary>
	class XorNet
	{
		INetwork Net;

		public XorNet()
		{
			Net = new BackProp(
				2,  /* 2 input connections  */
				new int[] {2, 2}, /* 2 layers with 2 neurons each */
				1 /* 1 output neuron */
				);

			Net.LearningRate = 0.5;
			Net.Momentum = 0.9;
			Net.Activation = new Sigmoid();
		}
	
		public void TestNet()
		{
			Console.WriteLine("0 xor 0 = 0 -> " + Net.Output(new double[] {0, 0}));
			Console.WriteLine("0 xor 1 = 1 -> " + Net.Output(new double[] {0, 1}));
			Console.WriteLine("1 xor 0 = 1 -> " + Net.Output(new double[] {1, 0}));
			Console.WriteLine("1 xor 1 = 0 -> " + Net.Output(new double[] {1, 1}));
		}

		public void TrainNet(bool bShowProgress)
		{
			Net.Randomize();
			double error;
			for (int i = 0; i < 10000; i++)
			{
				error = 0;
				error += Net.Train(new double[] {0, 0}, new double[] {0});
				error += Net.Train(new double[] {0, 1}, new double[] {1});
				error += Net.Train(new double[] {1, 0}, new double[] {1});
				error += Net.Train(new double[] {1, 1}, new double[] {0});

				if (bShowProgress)
                    Console.WriteLine(error);
			}
		}

		[STAThread]
		static void Main(string[] args)
		{
			XorNet xor = new XorNet();

			Console.WriteLine("*** before training ***");
			xor.TestNet();

			xor.TrainNet(false);

			Console.WriteLine();
			Console.WriteLine("*** after training ***");
			xor.TestNet();

			Console.ReadLine();
		}
	}
}
